﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace MoroMoro.Samples.ToDoList.Base.Domain.Expanders
{
    /// <summary>
    /// リフレクション処理を補助するメソッドを提供します。
    /// </summary>
    public static class ReflectionHelper
    {
        /// <summary>
        /// プロパティの値を返すラムダ式を式ツリーとして受け取り、式ツリーからプロパティのメタデータを取りだします。
        /// </summary>
        /// <typeparam name="T">プロパティが定義されているオブジェクトの型。</typeparam>
        /// <typeparam name="TResult">プロパティの型。</typeparam>
        /// <param name="propertyReturnsExpression">プロパティの値を返すラムダ式。</param>
        /// <returns>式ツリーから取りだされたプロパティのメタデータ。</returns>
        /// <exception cref="System.ArgumentNullException">propertyReturnsExpression が null です。</exception>
        /// <exception cref="System.ArgumentException">propertyReturnsExpression が、プロパティの値を返すラムダ式ではありません。</exception>
        public static PropertyInfo ExtractPropertyInfo<T, TResult>(Expression<Func<T, TResult>> propertyReturnsExpression)
        {
            if (propertyReturnsExpression == null)
            {
                throw new ArgumentNullException("propertyReturnsExpression");
            }

            var body = propertyReturnsExpression.Body as MemberExpression;
            if (body == null)
            {
                throw new ArgumentException("propertyReturnsExpression が、プロパティの値を返すラムダ式ではありません。");
            }

            var targetProperty = body.Member as PropertyInfo;
            if (targetProperty == null)
            {
                throw new ArgumentException("propertyReturnsExpression が、プロパティの値を返すラムダ式ではありません。");
            }

            return targetProperty;
        }
    }
}
